package com.wpml.juc;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedTransferQueue;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Description
 * @Date 2021-05-18
 * @Author wangpei
 **/
public class LockSupportTest {

    static volatile List<Integer> countDown_list = new ArrayList<>();
    static volatile List<Integer> lockSupport_list = new ArrayList<>();

    static Thread t1 = null, t2 = null;

    static char[] numArr = "1234567".toCharArray();
    static char[] strArr = "ABCDEFG".toCharArray();

    static final Object lock = new Object();

    enum ReadyToRun{T1,T2}

    static volatile ReadyToRun r = ReadyToRun.T1;

    public static void main(String[] args) {

//        casAndVolatilePrint();

        transferPrint_two();


//        synchronizedPrint();

//        transferPrint();
//        reentrantLockTest();
//        lockSupportTest2();
//        countDownLatchTest();
//        lockSupportTest();


        /*int i = 1;
        int j = i++;
        System.out.println(++j);
        if ((j > ++j) && (i++ == j)) {
            System.out.println(123);
            j += i;
        }
        System.out.println(j);*/

    }



    /**
     * @Description CAS 加 volatile 实现交替打印
     * @Date 2021/5/21 15:44
     * @Author wangpei
     **/
    private static void casAndVolatilePrint() {
        new Thread(() -> {
            for (char c : strArr) {
                while (r != ReadyToRun.T1) {}
                System.out.print(c);
                r = ReadyToRun.T2;
            }
        }).start();

        new Thread(() -> {
            for (char c : numArr) {
                while (r != ReadyToRun.T2) {}
                System.out.print(c);
                r = ReadyToRun.T1;
            }
        }).start();
    }

    /**
     * @Description 交替打印
     * @Date 2021/5/21 15:02
     * @Author wangpei
     **/
    private static void synchronizedPrint() {
        new Thread(() -> {
            synchronized (lock) {
                for (char c : strArr) {
                    System.out.print(c);
                    try {
                        lock.notify();
                        lock.wait(); // 释放锁
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                lock.notifyAll(); // 打印结束通知所有线程执行结束
            }
        }).start();

        new Thread(() -> {
            synchronized (lock) {
                for (char c : numArr) {
                    System.out.print(c);
                    try {
                        lock.notify();
                        lock.wait(); // 释放锁
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                lock.notifyAll(); // 打印结束通知所有线程执行结束
            }
        }).start();
    }

    /**
     * @Description 交替打印
     * @Date 2021/5/21 15:02
     * @Author wangpei
     **/
    private static void transferPrint() {
        LinkedTransferQueue<String> strQueue = new LinkedTransferQueue<>();
        LinkedTransferQueue<Integer> intQueue = new LinkedTransferQueue<>();

        String[] arrStr = {"A","B","C","D"};

        new Thread(() -> {
            try {
                for (String s : arrStr) {
                    strQueue.transfer(s);
                    System.out.print(intQueue.take());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }).start();

        new Thread(() -> {
            for (int i = 0; i < arrStr.length; i++) {
                try {
                    System.out.print(strQueue.take());
                    intQueue.transfer(i + 1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /**
     * @Description 交替打印
     * @Date 2021/5/21 15:02
     * @Author wangpei
     **/
    private static void transferPrint_two() {
        LinkedTransferQueue<Character> charQueue = new LinkedTransferQueue<>();

        new Thread(() -> {
            try {
                for (char s : numArr) {
                    System.out.print(charQueue.take());
                    charQueue.transfer(s);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }).start();

        new Thread(() -> {
            for (char s : strArr) {
                try {
                    charQueue.transfer(s);
                    System.out.print(charQueue.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    private static void reentrantLockTest() {
        ReentrantLock lock = new ReentrantLock();
        try {
            lock.lock();
            System.out.println(123);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * @Description 交替打印
     * @Date 2021/5/21 15:02
     * @Author wangpei
     **/
    private static void lockSupportTest2() {
        String[] arrStr = {"A","B","C","D"};
        t1 = new Thread(() -> {
            for (String s : arrStr) {
                System.out.print(s);
                LockSupport.unpark(t2);
                LockSupport.park();
            }
        });

        t2 = new Thread(() -> {
            for (int i = 1; i < 5; i++) {
                LockSupport.park();
                System.out.print(i);
                LockSupport.unpark(t1);
            }
        });

        t1.start();
        t2.start();
    }

    /**
     * @Description 线程 t1 执行到 5 通知 t2 线程 执行，t2 执行完 t1 继续执行
     * @Date 2021/5/21 15:05
     * @Author wangpei
     **/
    private static void countDownLatchTest() {
        CountDownLatch downLatch_t1 = new CountDownLatch(1);
        CountDownLatch downLatch_t2 = new CountDownLatch(1);
        t2 = new Thread(() -> {
            try {
                downLatch_t2.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("countDownLatchTest t2 结束");
            downLatch_t1.countDown();
        });
        t2.start();

        t1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println("countDownLatchTest " + i);
                countDown_list.add(i);
                if (countDown_list.size() == 5) {
                    downLatch_t2.countDown();
                    try {
                        downLatch_t1.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        t1.start();
    }

    /**
     * @Description 线程 t1 执行到 5 通知 t2 线程 执行，t2 执行完 t1 继续执行
     * @Date 2021/5/21 15:05
     * @Author wangpei
     **/
    private static void lockSupportTest() {
        t2 = new Thread(() -> {
            LockSupport.park();
            System.out.println("lockSupportTest t2 结束");
            LockSupport.unpark(t1);
        });
        t2.start();

        t1 = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                System.out.println("lockSupportTest " + i);
                lockSupport_list.add(i);
                if (lockSupport_list.size() == 5) {
                    LockSupport.unpark(t2);
                    LockSupport.park();
                }
            }
        });

        t1.start();
    }
}
